package jp.joogoo.web.controller;

import java.io.PrintWriter;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Logger;

import jp.joogoo.web.meta.M_joogooMeta;
import jp.joogoo.web.meta.T_newMeta;
import jp.joogoo.web.model.M_joogoo;
import jp.joogoo.web.model.M_service;
import jp.joogoo.web.model.T_new;

import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;
import org.slim3.datastore.Datastore;

import com.google.api.client.util.DateTime;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.appengine.repackaged.org.json.JSONArray;
import com.google.appengine.repackaged.org.json.JSONException;
import com.google.appengine.repackaged.org.json.JSONStringer;

public class NewsController extends Controller {
    private static final T_newMeta meta = new T_newMeta();
    private static final M_joogooMeta jmeta = new M_joogooMeta();
    private static final Logger logger = Logger.getLogger(NewsController.class
        .getName());

    @Override
    protected Navigation run() throws Exception {
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");

        UserService userService = UserServiceFactory.getUserService();
        User user = userService.getCurrentUser();

        String token = asString("access_token");
        String sinceStr = asString("since");

        logger.info("access_token:" + token);
        logger.info("since" + sinceStr);

        JSONStringer jsonResult = new JSONStringer();
        if (user != null || token != null) {
            if (user != null) {
                logger.info("user: " + user.getEmail());
                token = user.getUserId();
            }
            jsonResult.array();
            // 実装が間に合うようなら AuthorizeService#getAccounts() を使うようにしてください。 (作りかけ)
            // 認証済みアカウント情報が存在しない場合には空の配列を返しますので、if 文を省略できます。
            List<M_joogoo> joogoos =
                Datastore
                    .query(jmeta)
                    .filter(meta.userId.equal(token))
                    .asList();
            if (joogoos != null && joogoos.size() > 0) {
                for (M_joogoo joogoo : joogoos) {
                    M_service service = joogoo.getMServiceRef().getModel();
                    // 実装が間に合うようなら ContentsService#retrieve() を使うようにしてください。 (作りかけ)
                    // 引数は sinceStr の文字列ではなく Epoch からの経過時刻を想定しています。
                    JSONArray jsonNews =
                        buildNewsJson(joogoo, token, service, sinceStr);
                    jsonResult
                        .object()
                        .key("key")
                        .value(KeyFactory.keyToString(service.getKey()))
                        .key("name")
                        .value(service.getServiceName());
                    jsonResult.key("news").value(jsonNews).endObject();
                }
            }
            jsonResult.endArray();
        } else {
            jsonResult.object().key("error").value("ログインしていません").endObject();
        }

        logger.info("response:" + jsonResult.toString());
        PrintWriter writer = response.getWriter();

        writer.print(jsonResult.toString());

        response.flushBuffer();

        return null;
    }

    private JSONArray buildNewsJson(M_joogoo joogoo, String token,
            M_service service, String sinceStr) throws JSONException {
        // 時間を受け取った場合は、その時刻以降。無い場合は1日前からでデータを取得する。
        Date since = getDateFromStr(sinceStr);
        
        List<T_new> news =
            joogoo
                .getNewListRef()
                .query()
                .filter(meta.createdAt.greaterThan(since))
                .getModelList();
        logger.info("size: " + news.size());
        JSONArray jsonNews = new JSONArray();
        if (news != null && news.size() > 0) {
            for (T_new tnew : news) {
                HashMap<String, String> newHash = new HashMap<String, String>();
                newHash.put("key", KeyFactory.keyToString(tnew.getKey()));
                newHash.put("content", tnew.getNewText());
                newHash.put("createdAt", tnew.getCreatedAt().toString());
                newHash.put("title", tnew.getTitle());
                newHash.put("targetUrl", tnew.getContentUrl());
                newHash.put("author", tnew.getAuthor());
                newHash.put("serviceName", service.getServiceName());
                jsonNews.put(newHash);
            }
        }
        return jsonNews;
    }

    private Date getDateFromStr(String sinceStr) {
        Date since = null;

        try {
            DateTime d = DateTime.parseRfc3339(sinceStr);
            since = new Date(d.value);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
        if (since == null) {
            Date today = new Date();
            Calendar cal = new GregorianCalendar();
            cal.setTime(today);
            cal.add(Calendar.DAY_OF_MONTH, -1);
            Date oneDayAgo = cal.getTime();
            since = oneDayAgo;
        }

        return since;
    }
}